package com.mytools.common.example.threadPool;

import com.mytools.common.example.threadPool.reject.RejectHandler;
import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author LJK
 * @description
 * @date 2025/1/30
 */
@Data
public class MyThreadPool {
    private int coreThreadSize=10;
    private int maxSize=16;
    private int expiration_time=3;
    private TimeUnit time_unit=TimeUnit.SECONDS;
    private RejectHandler rejectHandler;

    public MyThreadPool(int coreThreadSize, int maxSize, int expiration_time, TimeUnit time_unit, RejectHandler rejectHandler, BlockingQueue<Runnable> blockingQueue) {
        this.coreThreadSize = coreThreadSize;
        this.maxSize = maxSize;
        this.expiration_time = expiration_time;
        this.time_unit = time_unit;
        this.rejectHandler = rejectHandler;
        this.blockingQueue = blockingQueue;
    }

    //阻塞任务队列
    BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(1024);
    //核心线程
    List<Thread> coreThreads = new ArrayList<>();
    //支援线程
    List<Thread> suppThreads = new ArrayList<>();
    class CoreThread extends Thread{
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable command = blockingQueue.take();
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    class SupportThread extends Thread{
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable command = blockingQueue.poll(expiration_time, time_unit);
                    if (command == null)
                        break;
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(Thread.currentThread().getName()+"辅助线程结束了");
        }
    }




    public void execute(Runnable runnable) {
        //核心线程未满
        if (coreThreads.size() < coreThreadSize) {
            Thread thread = new CoreThread();
            coreThreads.add(thread);
            thread.start();
        }

        //将任务丢入阻塞队列中
        //这里为什么使用offer而不用add，add在bq满的时候会抛出异常，而offer会返回false
        if (blockingQueue.offer(runnable))
            return;

        //开启支援线程
        if (suppThreads.size() <= maxSize - coreThreadSize) {
            Thread thread = new SupportThread();
            suppThreads.add(thread);
            thread.start();
        }

        if (!blockingQueue.offer(runnable)) {
            //开启拒绝策略
            rejectHandler.reject(runnable,this);
        }
    }


}


